﻿//LicenseClient.cs
//Copyright (c) 2013 StockSharp LLC, all rights reserved.
//This code module is part of StockSharp library.
//This code is licensed under the GNU GENERAL PUBLIC LICENSE Version 3.
//See the file License.txt for the license details.
//More info on: http://stocksharp.com

namespace StockSharp.Algo.Licensing
{
	using System;
	using System.ServiceModel;

	using Ecng.Collections;
	using Ecng.Common;
	using Ecng.Interop;
	using Ecng.Net;

	/// <summary>
	/// Клиент для доступа к сервису лицензирование StockSharp.
	/// </summary>
	public class LicenseClient : Disposable
	{
		private readonly Lazy<ChannelFactory<ILicenseService>> _factory;

		/// <summary>
		/// Создать <see cref="LicenseClient"/>.
		/// </summary>
		public LicenseClient()
			: this("http://stocksharp.com/services/licenseservice.svc".To<Uri>())
		{
		}

		/// <summary>
		/// Создать <see cref="LicenseClient"/>.
		/// </summary>
		/// <param name="address">Адрес сервиса.</param>
		public LicenseClient(Uri address)
		{
			if (address == null)
				throw new ArgumentNullException("address");

			Address = address;

			_factory = new Lazy<ChannelFactory<ILicenseService>>(
							() => ChannelHelper.Create("license",
								() => new ChannelFactory<ILicenseService>(new WSHttpBinding { Security = { Mode = SecurityMode.None } }, new EndpointAddress(address))));
		}

		/// <summary>
		/// Адрес сервиса.
		/// </summary>
		public Uri Address { get; private set; }

		/// <summary>
		/// Получить временную лицензию.
		/// </summary>
		/// <returns>Временная лицензия.</returns>
		public License GetTrialLicense()
		{
			return GetLicense(f => f.GetTrialLicense(HardwareInfo.Instance.Id));
		}

		/// <summary>
		/// Получить полную лицензию.
		/// </summary>
		/// <returns>Полная лицензия.</returns>
		public License GetFullLicense()
		{
			return GetLicense(f => f.GetFullLicense(ServerCredentials.Instance.Login, ServerCredentials.Instance.Password, HardwareInfo.Instance.Id));
		}

		private License GetLicense(Func<ILicenseService, byte[]> getLicense)
		{
			if (getLicense == null)
				throw new ArgumentNullException("getLicense");

			var licenseBody = _factory.Value.Invoke(getLicense);

			if (licenseBody.IsEmpty())
				throw new InvalidOperationException("Невозможно получить лицензию.");
			else if (licenseBody.Length == 1)
				RaiseException(licenseBody[0]);

			return new License(licenseBody);
		}

		/// <summary>
		/// Отправить лицензию на зарегистрированный email.
		/// </summary>
		public void SendFullLicense()
		{
			var errorCode = _factory.Value.Invoke(f => f.SendFullLicense(ServerCredentials.Instance.Login, ServerCredentials.Instance.Password, HardwareInfo.Instance.Id));

			if (errorCode != 0)
				RaiseException(errorCode);
		}

		/// <summary>
		/// Подписать исполняемый файл.
		/// </summary>
		/// <param name="fileBody">Файл.</param>
		/// <returns>Файл с цифровой подписью.</returns>
		public byte[] Sign(byte[] fileBody)
		{
			if (fileBody == null)
				throw new ArgumentNullException("fileBody");

			var retVal = _factory.Value.Invoke(f => f.SignExecutableFile(ServerCredentials.Instance.Login, ServerCredentials.Instance.Password, fileBody));

			if (retVal.IsEmpty())
				throw new InvalidOperationException("Невозможно подписать файл.");
			else if (retVal.Length == 1)
				RaiseException(retVal[0]);

			return retVal;
		}

		private static void RaiseException(byte errorCode)
		{
			switch (errorCode)
			{
				case 1:
					throw new InvalidOperationException("Неправильный логин или пароль.");
				case 2:
					throw new InvalidOperationException("Для данного IP адреса уже была ранее получена лицензия.");
				case 3:
					throw new InvalidOperationException("Вы уже получали лицензию для другого компьютера.");
				case 4:
					throw new InvalidOperationException("Пользователь временно заблокирован из-за неудачных попыток авторизации.");
				case 5:
					throw new InvalidOperationException("Нет прав для скачивания полной лицензии.");
				case 6:
					throw new InvalidOperationException("Лицензия отозвана.");
				case 7:
					throw new InvalidOperationException("Нет прав для подписывания файлов.");
				case 8:
					throw new InvalidOperationException("Пользователь заблокирован.");
				default:
					throw new InvalidOperationException("Неизвестный код ошибки сервера.");
			}
		}

		/// <summary>
		/// Освободить занятые ресурсы.
		/// </summary>
		protected override void DisposeManaged()
		{
			if (_factory.IsValueCreated)
				((IDisposable)_factory.Value).Dispose();

			base.DisposeManaged();
		}
	}
}